SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00003 1 05-25-9408:24ALL TONI PERRETTA Timing Functions SWAG9405 27 «u {π ▌Is there an easy way to time functions and/or procedures?? I'm tryingπ ▌to compare a couple functions that do the samething and I would like toπ ▌time them. I've tried using the GetTime procedure but the hundredths ofπ ▌seconds isn't fast enough. Can any one help?ππ I think this unit may help you:ππ***************************************************************************π}πunit tptimer;ππinterfaceππprocedure cardinal(l:longint; var result:double);ππprocedure elapsedtime(start:longint; stop:longint; var result:double);π(*Calculate time elapsed (in milliseconds) between Start and Stop*)ππprocedure initializetimer;π(*Reprogram the timer chip to allow 1 microsecond resolution*)ππprocedure restoretimer;π(*Restore the timer chip to its normal state*)ππfunction readtimer:longint;π(*Read the timer with 1 microsecond resolution*)ππimplementationπuses dos;ππconstπTimerResolution=1193181.667;ππprocedure cardinal(l:longint; var result:double);π Beginπ if l < 0 then result:= l + 4294967296.0π elseπ result := l;π End;ππprocedure elapsedtime(start, stop:longint; var result:double);π var r:double;π Beginπ cardinal(stop - start, r);π result := (1000 * r) / TimerResolution;π End;ππprocedure initializetimer;πlabel NullJump1,NullJump2;πBeginπ port[$043]:=$034;π asm jmp NullJump1;π NullJump1:π end;π port[$040]:=$000;π asm jmp NullJump2π NullJump2:π end;π port[$040]:=$000;πEnd;ππprocedure restoretimer;πlabel NullJump1,NullJump2;πBeginπ port[$043]:=$036;π asm jmp NullJump1;π NullJump1:π end;π port[$040]:=$000;π asm jmp NullJump2π NullJump2:π end;π port[$040]:=$000;πEnd;ππfunction readtimer:longint; assembler;πlabel done;πAsmπ cli (* Disable interrupts *)π mov dx,020h (* Address PIC ocw3 *)π mov al,00Ah (* Ask to read irr *)π out dx,alπ mov al,00h (* Latch timer 0 *)π out 043h,alπ in al,dx (* Read irr *)π mov di,ax (* Save it in DI *)π in al,040h (* Counter --> bx*)π mov bl,al (* LSB in BL *)π in al,040hπ mov bh,al (* MSB in BH *)π not bx (* Need ascending counter *)π in al,021h (* Read PIC imr *)π mov si,ax (* Save it in SI *)π mov al,00FFh (* Mask all interrupts *)π out 021h,alπ mov ax,040h (* read low word of time *)π mov es,ax (* from BIOS data area *)π mov dx,es:[06Ch]π mov ax,si (* Restore imr from SI *)π out 021h,alπ sti (* Enable interrupts *)π mov ax,di (* Retrieve old irr *)π test al,001h (* Counter hit 0? *)π jz done (* Jump if not *)π cmp bx,0FFh (* Counter > 0x0FF? *)π ja done (* Done if so *)π inc dx (* Else count int req. *)πdone:π mov ax,bx (* set function result *)πEnd;ππEnd.ππ***********************************************************************ππand here is a program to test the unit:ππProgram TestTime;πuses crt, dos, tptimer;π var start_time, stop_time: longint;π time:double;πBeginπ Clrscr;π initializetimer;π delay(100);π start_time:=readtimer;π delay(2);π stop_time:=readtimer;π elapsedtime(start_time, stop_time, time);π writeln('elapsed time = ', time:0:10);π readln;π restoretimer;πEnd.ππ 2 05-26-9406:18ALL MARTIN ROMMEL Stop Watch Function SWAG9405 19 «u {ππI am sure it is not the most elegant implementation. Except for the nightπof February 29th to March 1st, it should work fine. You might want toπthrough out the escape and beep procedures. }ππππunit Time; {JMR'91} { Unit zur Bestimmung von Programmlaufzeiten }ππinterfaceππ uses DOS,Crt;ππ procedure Start;π procedure Elapsed(var Hour,Minute,Second,HundSec:Word); π function ElapsedStr:String; { 'HH:MM:SS,HH' }π { Elapsed und ElapsedStr ermitteln die Zeit, die seit dem Aufruf von }π { Start vergangen ist. Schaltjahre werden nicht berücksichtigt. }π procedure beep; { gibt kurzen Ton }π function escape:Boolean; { true, wenn <Esc> gedrückt wurde (ReadKey) }π{***************************************************************************}ππimplementationππvar Y,Month,Day,DoW,Month0,Day0,Hour0,Minute0,Second0,HundSec0:Word;ππprocedure Start;π beginπ GetTime(Hour0,Minute0,Second0,HundSec0);π GetDate(Y,Month0,Day0,DoW);π end;ππprocedure Elapsed;π beginπ GetTime(Hour,Minute,Second,HundSec);π GetDate(Y,Month,Day,DoW);π HundSec:=HundSec-HundSec0;π if HundSec>99 then begin HundSec:=HundSec+100; dec(Second) end;π Second:=Second-Second0;π if Second>59 then begin Second:=Second+60; dec(Minute) end;π Minute:=Minute-Minute0;π if Minute>59 then begin Minute:=Minute+60; dec(Hour) end;π Hour:=Hour-Hour0;π Day:=Day-Day0;π if Day>30 then if Month in [1,3,5,7,8,10,12] then Day:=Day+31π else if Month<>2 then Day:=Day+30π else Day:=Day+28;π if Hour>23 then Hour:=Hour+24*Day;π end;ππfunction ElapsedStr;π var Hour,Minute,Second,HundSec:Word;π function LeadingZero(w:Word):String;π var s:String;π beginπ Str(w:0,s);π if Length(s)=1 then s:='0'+s;π LeadingZero:=s;π end;π beginπ Elapsed(Hour,Minute,Second,HundSec);π ElapsedStr:=LeadingZero(Hour)+':'+LeadingZero(Minute)+':'π +LeadingZero(Second){+','+LeadingZero(HundSec)};π end;ππprocedure beep;π beginπ sound(440);π delay(10);π nosound;π end;ππfunction Escape;π var Taste:Char;π beginπ if Keypressed thenπ if Ord(ReadKey)=27 then Escape:=trueπ else Escape:=falseπ else Escape:=false;π end;ππend. { Unit Time }π 3 05-26-9407:30ALL SOUTHERN SOFTWARE Wait Correction SWAG9405 50 «u π{$A+,B-,E-,F-,I-,N-,O-,R-,S-,V-}ππ(*πFastWait Copyright (c) 1991 Southern SoftwareππVersion 1.00 - 4/8/91ππAllows PC's faster than 20 mhz (386/486) to properly use a delayπfunction based upon a null looping procedure such as is used in theπTurbo Pascal "Delay" procedure. Wait is accurate for PC's as fast asπ1,100 mhz equivalent!ππUSAGE: Simply place "FastWait" in the Uses section of your programπ and replace each occurrence of "delay" in your program withπ "wait".ππExample-π=======ππ Existing program:π ----------------π Uses CRT;ππ beginπ writeln('This program delays for 5 seconds.);π delay(5000);π end.ππ New program:π -----------π Uses FastWait, CRT; {Now also uses "FastWait"}ππ beginπ writeln('This program delays for 5 seconds.);π wait(5000); {changed "delay" to "wait"}π end.π*)ππunit FastWait;ππ (* Version 1.00 - 4/8/91 *)ππ {$ifdef DEBUG}π {$D+,L+}π {$else}π {$D-,L-}π {$endif}ππ(****************************************************************************)π interfaceπ(****************************************************************************)ππvarπ (* Number of loops to do for 1 ms wait. *)π WaitOneMS : word;ππ (* Number of loops per timer tick. *)π LoopsPerTick : longint;ππ (* System timer, 18.2/second. *)π BIOSTick : longint absolute $40:$6C;ππ (* Pauses execution for "ms" milliseconds. *)πprocedure Wait(ms : word);ππ{$ifdef VER60}ππ (* This procedure is for very short timing loops ( < 1ms)π that cannot be handled by the delay routine.ππ The variable "LoopsPerTick" has the number of loopsπ to do for one BIOS tick (18.2 of these/sec). If youπ want to delay for "X" µs, the number of loops requiredπ would be "(LoopsPerTick * X) div 54945". This will notπ compile if you are using TP 4.0, 5.0 or 5.5 due to theπ conditional defines. This is because it makes use ofπ the "asm" statement which is not available in TPπ versions prior to 6.0. *)ππ procedure ShortDelay(NumLoops : word);π π{$endif}πππ(****************************************************************************)π implementationπ(****************************************************************************)ππ {$L WAIT.OBJ}ππ procedure Wait(ms : word); external;ππ procedure WaitInit; external;ππ{$ifdef VER60}ππ procedure ShortDelay(NumLoops : word); assembler;π asmπ mov cx,NumLoopsπ jcxz @@2π xor di,di (* ES:DI points to dummy address *)π mov es,di (* which won't change *)π mov al,es:[di] (* AL has the value there *)π @@1:π cmp al,es:[di]π jne @@2π loop @@1π @@2:π end;ππ{$endif}ππBEGIN (* Code to execute at start-up to calibrate the loop *)π (* delay. *)π WaitInitπEND.ππ{ XX3402 Code to WAIT.OBJπ{ Cut and save as WAIT.XX. Execute : XX3402 D WAIT.XX to create WAIT.OBJ }π{ ------------------ CUT HERE -------------------------- }πππ*XX3402-000319-080491--72--85-45848--------WAIT.OBJ--1-OF--1πU+c+03R-GJEiEJBB8cUU++++J5JmMawUELBnNKpWP4Jm60-KNL7nOKxi616iA145W-++ECbgπgsUK03R-GJEiEJBBhcU1+21dH7M0++-cW+A+E84IZUM+-2F-J234a+Q+8++++U2-BNM4++F1πHoF3FNU5+0VR++A-+RSA4U+7Jo37J2xCFIpH++lAHoxEIp-3IZF7Eog+vt+D+++003R-GJF7πHYZI8+++ld+9+++0-3R-GJE6+++WW+E+E86-YO-V++6++0Mu-LI0sjb1WxkqWpQ20x7o2nDzπXgQaWUK95U++Wwjcrjx8RTX8+U0sE+0Ck9xg+9bzznDG7cc37Xc3RDgaWUIaCUJp-S9tEijqπi1Q+YTTEck++WFM0+DTlck++kzWQ3E124kM-+QFF-U20l3I4+E92KUM-+E88+U++R+++π***** END OF BLOCK 1 *****ππ{ -------------------------- CUT HERE ------------------------ }π{ TEST PROGRAM }ππprogram TestWait;πusesπ crt,π FastWait;ππvarπ Counter : word;π jj : longint;ππBEGINπ clrscr;π HighVideo;π writeln(' Southern Software (c) 1991'#10);π LowVideo;π writeln('This test compares the standard "delay" routine with our new "Wait"');π writeln('procedure. Below is the calculated number of small loops the PC goes');π writeln('through for one millisecond delay. If this number is above 1,191 then');π writeln('the "delay" routine in the Turbo CRT unit as well as those in the');π writeln('TurboPower Software Object Professional and Turbo Professional series');π writeln('will yield delays that are too short. Our "wait" procedure is the same');π writeln('as the "delay" procedure except that it will adjust for faster machines.');π writeln;π writeln('The looping below is for 10 seconds in each case. The seconds are shown');π writeln('and at the end, the number of BIOS ticks is shown. A properly calibrated');π writeln('delay routine should be almost exactly 10 seconds long, which is 182 ticks.');π writeln;π writeln('To abort at any time, press any key.');π writeln(#10);π write('The delay factor for this machine is actually ');π HighVideo;π writeln(WaitOneMS);π LowVideo;π writeln(#10);π writeln('10 second delays using');π write(' CRT unit "delay" : ');π HighVideo;π (* Delay 10 seconds using the CRT unit "delay" routine. *)π jj := BIOSTick;π repeatπ until (jj <> BIOSTick);π jj := BIOSTick;π for Counter := 1 to 10 do π beginπ delay(1000);π write(Counter)π end;π jj := (BIOSTick - jj);π LowVideo;π write(' BIOS Ticks : ');π HighVideo;π writeln(jj);π LowVideo;π write('FastWait unit "wait" : ');π HighVideo;π (* Delay 10 seconds using FastWait unit "wait" routine. *)π jj := BIOSTick;π repeatπ until (jj <> BIOSTick);π jj := BIOSTick;π for Counter := 1 to 10 do π beginπ wait(1000);π write(Counter)π end;π jj := (BIOSTick - jj);π LowVideo;π write(' BIOS Ticks : ');π HighVideo;π writeln(jj, #10);π LowVideo;π write('Press any key to end ');π repeatπ until keypressed;π while keypressed doπ Counter := ord(ReadKey);π clrscrπEND.πππ